﻿//-----------------------------------------------------------------------
// <copyright file="TaxonomyHelper.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
// </copyright>
// <author>Yogesh M Joshi</author>
// <email>ymjoshi@live.com</email>
// <date>16-May-2011</date>
//-----------------------------------------------------------------------

namespace SmartTag.Common.Taxonomy
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Taxonomy;
    using SmartTag.Common.Utility;

    /// <summary>
    /// Taxonomy operations
    /// </summary>
    public static class TaxonomyHelper
    {
        /// <summary>
        /// Load all possible terms for give list column
        /// </summary>
        /// <param name="column">Taxonomy column</param>
        /// <returns>List of terms</returns>
        public static List<Term> LoadTerms(SPField column)
        {
            // Terms collection
            List<Term> terms = new List<Term>();

            try
            {
                SPWeb web = column.ParentList.ParentWeb;
                TermStore termStore = GetTermStore(web);
                TaxonomyField taxField = column as TaxonomyField;

                // Check if we have the field that is the TaxonomyField
                if (taxField != null && taxField.TypeAsString.Equals("TaxonomyFieldTypeMulti", StringComparison.OrdinalIgnoreCase))
                {
                    // Check if column is pointing to term set
                    if (taxField.AnchorId != Guid.Empty)
                    {
                        Guid termId = taxField.AnchorId;
                        Term term = termStore.GetTerm(termId);

                        // Get all terms
                        bool ret = TryGetTermsRecursively(term, terms, true);
                    }
                    else
                    {
                        // Get the GUID of term set
                        Guid termSetId = taxField.TermSetId;

                        // Column is pointing to term set
                        TermSet termSet = termStore.GetTermSet(termSetId);
                        terms = termSet.GetAllTerms().ToList<Term>();
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error occured in LoadTerms", (int)TraceLogEventId.LoadTerms);
            }

            return terms;
        }

        /// <summary>
        /// Get all child terms recursively for given term
        /// </summary>
        /// <param name="parentTerm">Parent term</param>
        /// <param name="descendentTerms">Descendant terms</param>
        /// <param name="includeDeprecated">Shall include deprecated</param>
        /// <returns>Status true or false</returns>
        private static bool TryGetTermsRecursively(Term parentTerm, List<Term> descendentTerms, bool includeDeprecated)
        {
            bool flag = false;

            try
            {
                List<Term> list;
                if (TryGetDescendantTerms(out list, parentTerm))
                {
                    flag = true;
                    if ((list == null) || (list.Count <= 0))
                    {
                        return flag;
                    }

                    descendentTerms.AddRange(list);
                    foreach (Term term in list)
                    {
                        if (includeDeprecated || !term.IsDeprecated)
                        {
                            flag = TryGetTermsRecursively(term, descendentTerms, includeDeprecated);
                            if (!flag)
                            {
                                return flag;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error occured in TryGetTermsRecursively", (int)TraceLogEventId.TryGetTermsRecursively);
            }

            return flag;
        }

        /// <summary>
        /// Get all descendant terms for current term
        /// </summary>
        /// <param name="list">List of descendant terms</param>
        /// <param name="parentTerm">Parent term</param>
        /// <returns>Status true or false</returns>
        private static bool TryGetDescendantTerms(out List<Term> list, Term parentTerm)
        {
            try
            {
                TermCollection coll = parentTerm.GetTerms(1000);
                list = new List<Term>();

                foreach (Term term in coll)
                {
                    list.Add(term);
                }

                return true;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error occured in TryGetDescendantTerms", (int)TraceLogEventId.TryGetDescendantTerms);
                list = null;
                return false;
            }
        }

        /// <summary>
        /// Get term store for web
        /// </summary>
        /// <param name="web">SPWeb to get term store for</param>
        /// <returns>Term store object</returns>
        private static TermStore GetTermStore(SPWeb web)
        {
            return GetTermStore(web.Site);
        }

        /// <summary>
        /// Get the term store for current site
        /// </summary>
        /// <param name="site">Site to get term store for</param>
        /// <returns>Term store object</returns>
        private static TermStore GetTermStore(SPSite site)
        {
            try
            {
                TaxonomySession session = new TaxonomySession(site);
                TermStore termStore = session.DefaultSiteCollectionTermStore;
                return termStore;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error occured in GetTermStore", (int)TraceLogEventId.GetTermStore);
                return null;
            }
        }
    }
}
